
#include "http_svr.h"
#include <stdint.h>
#include <istream>
#include <iostream>
#include "http_dvr_cmd.h"
struct mg_serve_http_opts HttpService::s_http_server_opts;

//请求事件处理
void HttpService::mgEvHandler(struct mg_connection* nc, int ev, void* p) { // 形参好像固定是这三种类型
    //处理request
    Json::Value rsq;
    struct http_message* hm = (struct http_message*)p;
    HttpService* handle = (HttpService*)nc->user_data;
    switch (ev)
    {
    case MG_EV_HTTP_REQUEST:
        if (mg_vcmp(&hm->method, "GET") == 0)
        {
            static struct mg_serve_http_opts opts = { 0 };
            opts.document_root = "./www/";
            opts.index_files = "index.html";
            opts.enable_directory_listing = "yes";
            // std::cout << hm->uri.p << std::endl;
            mg_serve_http(nc, hm, opts);
            return;
        }
        else if (mg_vcmp(&hm->method, "POST") == 0)
        {
            std::string apiurl(hm->uri.p, hm->uri.len);
            std::string body(hm->body.p, hm->body.len);
            std::cout << hm->uri.p << std::endl;
            std::cout << body.c_str() << std::endl;
            if (http_dvr_cmd::GetMng()->CheckUrl(apiurl, rsq))
            {
                rsq.clear();
                http_dvr_cmd::GetMng()->run(body, rsq);
            }
            else
            {
                rsq["code"] = 400;
                rsq["msg"] = "error cmd";
            }
            handle->HttpRspJson(nc, rsq);
            return;
        }
        else
        {

            return ;
        }
    }
    //if (ev == MG_EV_HTTP_REQUEST) {
    //    struct http_message* msg = (struct http_message*)p;

    //    //body内容
    //    char* body = new char[msg->body.len + 1];
    //    memset(body, 0, msg->body.len + 1);
    //    memcpy(body, msg->body.p, msg->body.len);

    //    //uri内容
    //    char* uri = new char[msg->uri.len + 1];
    //    memset(uri, 0, msg->uri.len + 1);
    //    memcpy(uri, msg->uri.p, msg->uri.len);

    //    //返回body信息
    //    mgSendBody(nc, "body content");

    //    //返回下载文件
    //    //mgSendFile("相对于s_http_server_opts.document_root的文件路径");
    //}
    //else {
    //    mg_serve_http(nc, hm, s_http_server_opts); /* Serve static content */
//    }
    //    delete uri;
    //    delete body;
    //}
}

void HttpService::HttpRspJson(mg_connection* nc, Json::Value& rsq)
{
    if (!nc)
    {
        return;
    }
    // support ORCS
    // "Access-Control-Allow-Origin: *\r\n"
    // "Access-Control-Expose-Headers: *\r\n"
    // "Access-Control-Allow-Headers: *\r\n"
    // "Access-Control-Allow-Methods: *\r\n"

    Json::FastWriter FastWriter;
    std::string data =  FastWriter.write(rsq);
    mg_printf(nc,
        "HTTP/1.1 200 OK\r\n"
        "Content-Type: application/json\r\n"
        "Connection: close\r\n"
        "Content-Length: %u\r\n\r\n"
        "%s\r\n",
        (uint32_t)data.size(), data.c_str());
    nc->flags |= MG_F_SEND_AND_CLOSE;
    return;
}

//发送body信息
void HttpService::mgSendBody(struct mg_connection* nc, const char* content) {
    mg_send_head(nc, 200, strlen(content), "Content-Type: text/plain\r\nConnection: close");
    mg_send(nc, content, strlen(content));
    nc->flags |= MG_F_SEND_AND_CLOSE;
}

//发送文件，文件的位置是相对于s_http_server_opts.document_root的路径
void HttpService::mgSendFile(struct mg_connection* nc, struct http_message* hm, const char* filePath) {
    mg_http_serve_file(nc, hm, filePath, mg_mk_str("text/plain"), mg_mk_str(""));
}

//初始化并启动
bool HttpService::start(const char* port) {
    struct mg_mgr mgr;
    struct mg_connection* nc;

    mg_mgr_init(&mgr, NULL);
    printf("Starting web server on port %s\n", port);
    nc = mg_bind(&mgr, port, mgEvHandler);
    if (nc == NULL) {
        printf("Failed to create listener\n");
        return false;
    }

    // Set up HTTP server parameters
    mg_set_protocol_http_websocket(nc);
    s_http_server_opts.document_root = "/mnt/D/web/www/";  //文件相对路径 Serve current directory
    s_http_server_opts.enable_directory_listing = "yes";
    s_http_server_opts.index_files = "index.html";
    for (;;) {
        mg_mgr_poll(&mgr, 5000); //1s轮训一次
    }
    mg_mgr_free(&mgr);

    return true;
}
